package org.dromara.patrol.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.collection.CollUtil;
import lombok.extern.log4j.Log4j2;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.web.core.BaseController;
import org.dromara.patrol.domain.PatrolActionStatistics;
import org.dromara.patrol.domain.bo.StatisticsCountBo;
import org.dromara.patrol.domain.vo.ProblemRankVo;
import org.dromara.patrol.domain.vo.StatisticsCountTimeVo;
import org.dromara.patrol.domain.vo.StatisticsCountVo;
import org.dromara.patrol.service.IPatrolActionStatisticsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.List;

/**
 * 巡店结果统计
 *
 * @author han
 * @date 2024-4-23 09:26:00
 */
@SaIgnore
@Log4j2
@RestController
@RequestMapping("/result")
public class PatrolResultController extends BaseController {

    @Resource
    private IPatrolActionStatisticsService patrolActionStatisticsService;


    /**
     * 不合符评分项占比、得分率、整改率、整改完成率
     */
    @GetMapping("/statistics/count")
    public R<StatisticsCountVo> statisticsCount(@RequestBody @Validated StatisticsCountBo bo) {
        StatisticsCountTimeVo timeVo = getStatisticsCountTimeVo(bo);
        List<PatrolActionStatistics> list = patrolActionStatisticsService.selectList(bo, timeVo);

        // 本周数据
        List<PatrolActionStatistics> nowList = list.stream()
                .filter(p -> p.getLastPatrolTime() >= timeVo.getStartTime() && p.getLastPatrolTime() <= timeVo.getEndTime())
                .toList();


        // 上一周的数据
        List<PatrolActionStatistics> lastList = list.stream()
                .filter(p -> p.getLastPatrolTime() >= timeVo.getLastCycleStartTime() &&
                        p.getLastPatrolTime() <= timeVo.getLastCycleEndTime())
                .toList();
        StatisticsCountVo vo = new StatisticsCountVo();

        // 不合格评分项占比   不合格评分项数量 / （评分总项 - 不适用评分项）
        buildProblemRate(vo, nowList, lastList);
        // 得分率  得分总数/所有评分项总分
        buildScoreRate(vo, nowList, lastList);
        // 整改率 发生整改的巡店次数/总共发起的巡店次数
        buildRectifyRate(vo, nowList, lastList);
        // 整改完成率 整改完成的巡店次数 / 总共发生的整改的巡店次数
        buildRectifyDoneRate(vo, nowList, lastList);
        return R.ok(vo);
    }

    /**
     * 门店问题频次排行
     * @param bo    巡店结果统计请求入参
     * @return      ProblemRankVo 门店问题频次排行对象
     */
    @GetMapping("/problemRank")
    public R<List<ProblemRankVo>> problemRank(@RequestBody @Validated StatisticsCountBo bo) {
        StatisticsCountTimeVo timeVo = getStatisticsCountTimeVo(bo);
        return R.ok(patrolActionStatisticsService.getProblemRank(bo, timeVo));
    }

    /**
     * 整改完成率 整改完成的巡店次数 / 总共发生的整改的巡店次数
     * @param vo            vo
     * @param nowList       本周期数据
     * @param lastList      上周期数据
     */
    private void buildRectifyDoneRate(StatisticsCountVo vo, List<PatrolActionStatistics> nowList, List<PatrolActionStatistics> lastList) {
        // 整改完成率 整改完成的巡店次数 / 总共发生的整改的巡店次数
        long count = nowList.stream().filter(a -> CollUtil.isNotEmpty(a.getAssignRectifyPersons()) && 0 == a.getRectifyPass()).count();
        long totalSize = nowList.stream().filter(a -> CollUtil.isNotEmpty(a.getAssignRectifyPersons())).count();

        long lastCount = lastList.stream().filter(a -> CollUtil.isNotEmpty(a.getAssignRectifyPersons()) && 0 == a.getRectifyPass()).count();
        long lastTotalSize = lastList.stream().filter(a -> CollUtil.isNotEmpty(a.getAssignRectifyPersons())).count();

        if (totalSize < 1) {
            vo.setRectifyDoneRate(0.0);
        } else {
            double d = (count / (double)totalSize) * 100;
            vo.setRectifyDoneRate(Double.parseDouble(String.format("%.2f", d)));
        }

        if (lastTotalSize < 1) {
            vo.setRectifyDoneRateLastCycle(0.0);
        } else {
            double d = (lastCount / (double)lastTotalSize) * 100;
            vo.setRectifyDoneRateLastCycle(Double.parseDouble(String.format("%.2f", d)));
        }

    }

    /**
     * 整改率 发生整改的巡店次数/总共发起的巡店次数
     * @param vo            vo
     * @param nowList       本周期数据
     * @param lastList      上周期数据
     */
    private void buildRectifyRate(StatisticsCountVo vo, List<PatrolActionStatistics> nowList, List<PatrolActionStatistics> lastList) {
        // 整改率 发生整改的巡店次数/总共发起的巡店次数
        long count = nowList.stream().filter(a -> CollUtil.isNotEmpty(a.getAssignRectifyPersons())).count();
        int totalSize = nowList.size();


        long lastCount = lastList.stream().filter(a -> CollUtil.isNotEmpty(a.getAssignRectifyPersons())).count();
        int lastTotalSize = lastList.size();

        if (totalSize < 1) {
            vo.setRectifyRate(0.0);
        } else {
            double d = (count / (double)totalSize) * 100;
            vo.setRectifyRate(Double.parseDouble(String.format("%.2f", d)));
        }

        if (lastTotalSize < 1) {
            vo.setRectifyRateLastCycle(0.0);
        } else {
            double d = (lastCount / (double)lastTotalSize) * 100;
            vo.setRectifyRateLastCycle(Double.parseDouble(String.format("%.2f", d)));
        }
    }

    /**
     * 得分率
     * @param vo            vo
     * @param nowList       本周期数据
     * @param lastList      上周期数据
     */
    private void buildScoreRate(StatisticsCountVo vo, List<PatrolActionStatistics> nowList, List<PatrolActionStatistics> lastList) {
        // 得分率  得分总数/所有评分项总分
        BigDecimal score = nowList.stream().map(PatrolActionStatistics::getScore).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal totalScore = nowList.stream().map(PatrolActionStatistics::getTotalScore).reduce(BigDecimal.ZERO, BigDecimal::add);


        BigDecimal lastScore = lastList.stream().map(PatrolActionStatistics::getScore).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal lastTotalScore = lastList.stream().map(PatrolActionStatistics::getTotalScore).reduce(BigDecimal.ZERO, BigDecimal::add);

        if (totalScore.compareTo(BigDecimal.ZERO) < 1) {
            vo.setScoreRate(0.0);
        } else {
            double v = score.divide(totalScore, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue();
            vo.setScoreRate(v);
        }
        if (lastTotalScore.compareTo(BigDecimal.ZERO) < 1) {
            vo.setScoreRateLastCycle(0.0);
        } else {
            double v = lastScore.divide(lastTotalScore, 4, RoundingMode.HALF_UP).multiply(new BigDecimal("100")).doubleValue();
            vo.setScoreRateLastCycle(v);
        }
    }

    /**
     * 不合格评分项占比
     * @param vo            vo
     * @param nowList       本周期数据
     * @param lastList      上周期数据
     */
    private void buildProblemRate(StatisticsCountVo vo, List<PatrolActionStatistics> nowList, List<PatrolActionStatistics> lastList) {
        // 不合格评分项占比   不合格评分项数量 / （评分总项 - 不适用评分项）
        int problemNum = nowList.stream().mapToInt(PatrolActionStatistics::getProblemNumber).sum();
        int checkItemNum = nowList.stream().mapToInt(PatrolActionStatistics::getCheckItemNumber).sum();
        int notApplicableNum = nowList.stream().mapToInt(PatrolActionStatistics::getNotApplicableNumber).sum();

        int lastProblemNum = lastList.stream().mapToInt(PatrolActionStatistics::getProblemNumber).sum();
        int lastCheckItemNum = lastList.stream().mapToInt(PatrolActionStatistics::getCheckItemNumber).sum();
        int lastNotApplicableNum = lastList.stream().mapToInt(PatrolActionStatistics::getNotApplicableNumber).sum();

        // 设置不合格的评分项数
        vo.setProblemItem(problemNum);
        // 设置评分总项数
        vo.setCheckItemTotal(checkItemNum);

        int num = checkItemNum - notApplicableNum;
        int lastNum = lastCheckItemNum - lastNotApplicableNum;
        if (num <= 0) {
            vo.setProblemItemRate(0.0);
        } else {
            double d =  (problemNum / (double)num) * 100;
            vo.setProblemItemRate(Double.parseDouble(String.format("%.2f", d)));
        }
        if (lastNum <= 0) {
            vo.setProblemItemRateLastCycle(0.0);
        } else {
            double d = (lastProblemNum / (double)lastNum) * 100;
            vo.setProblemItemRateLastCycle(Double.parseDouble(String.format("%.2f", d)));
        }

    }


    /**
     * 计算上一周期的开始时间和结束时间
     * @param bo    巡店结果统计
     * @return      周期时间
     */
    public StatisticsCountTimeVo getStatisticsCountTimeVo(StatisticsCountBo bo) {
        Long startTime = bo.getStartTime();
        Long endTime = bo.getEndTime();
        if (startTime > endTime) {
            throw new ServiceException("请选择正确的时间");
        }

        startTime = DateUtils.getStartTimeByTime(startTime);
        endTime = DateUtils.getEndTimeByTime(endTime);

        // 计算两个时间的天数差
        int day = DateUtils.differentDaysByMillisecond(new Date(startTime), new Date(endTime));
        // 获取上一 “周期”的开始时间和结束时间
        long lastCycleEndTime = startTime - 1;
        Instant now = Instant.ofEpochMilli(lastCycleEndTime);
        // 使用minus方法计算7天前的时间
        Instant sevenDaysAgo = now.minus(day, ChronoUnit.DAYS);
        long lastCycleStartTime = sevenDaysAgo.toEpochMilli();

        StatisticsCountTimeVo vo = new StatisticsCountTimeVo();
        vo.setLastCycleStartTime(lastCycleStartTime);
        vo.setLastCycleEndTime(lastCycleEndTime);
        vo.setStartTime(startTime);
        vo.setEndTime(endTime);

        return vo;
    }

}
